{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# NumPy Basics: Arrays and Vectorized Computation"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 71,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-01-29T23:14:12.648305Z",
     "start_time": "2019-01-29T23:14:12.614749Z"
    },
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "%matplotlib inline"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 72,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-01-29T23:14:12.681743Z",
     "start_time": "2019-01-29T23:14:12.650819Z"
    },
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "from __future__ import division\n",
    "from numpy.random import randn\n",
    "import numpy as np\n",
    "np.set_printoptions(precision=4, suppress=True)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## The NumPy ndarray: a multidimensional array object"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 73,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-01-29T23:14:12.718727Z",
     "start_time": "2019-01-29T23:14:12.684620Z"
    }
   },
   "outputs": [],
   "source": [
    "data = randn(2, 3)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 74,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-01-29T23:14:12.759899Z",
     "start_time": "2019-01-29T23:14:12.721696Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[-0.1525, -0.3262,  0.0097],\n",
       "       [-1.0739,  3.1669,  1.5573]])"
      ]
     },
     "execution_count": 74,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "data\n",
    "data * 10\n",
    "data + data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 75,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-01-29T23:14:12.805787Z",
     "start_time": "2019-01-29T23:14:12.768236Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "dtype('float64')"
      ]
     },
     "execution_count": 75,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "data.shape\n",
    "data.dtype"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Creating ndarrays"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 76,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-01-29T23:14:12.841269Z",
     "start_time": "2019-01-29T23:14:12.808790Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ 6. ,  7.5,  8. ,  0. ,  1. ])"
      ]
     },
     "execution_count": 76,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "data1 = [6, 7.5, 8, 0, 1]\n",
    "arr1 = np.array(data1)\n",
    "arr1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 77,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-01-29T23:14:12.871719Z",
     "start_time": "2019-01-29T23:14:12.844527Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(2, 4)"
      ]
     },
     "execution_count": 77,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "data2 = [[1, 2, 3, 4], [5, 6, 7, 8]]\n",
    "arr2 = np.array(data2)\n",
    "arr2\n",
    "arr2.ndim\n",
    "arr2.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 78,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-01-29T23:14:12.914817Z",
     "start_time": "2019-01-29T23:14:12.873912Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "dtype('int64')"
      ]
     },
     "execution_count": 78,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr1.dtype\n",
    "arr2.dtype"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 79,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-01-29T23:14:12.967800Z",
     "start_time": "2019-01-29T23:14:12.919238Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[[ 5.,  5.],\n",
       "        [ 5.,  5.],\n",
       "        [ 3.,  3.]],\n",
       "\n",
       "       [[ 3.,  3.],\n",
       "        [ 1.,  1.],\n",
       "        [ 1.,  1.]]])"
      ]
     },
     "execution_count": 79,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.zeros(10)\n",
    "np.zeros((3, 6))\n",
    "np.empty((2, 3, 2))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 80,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-01-29T23:14:13.003485Z",
     "start_time": "2019-01-29T23:14:12.971009Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14])"
      ]
     },
     "execution_count": 80,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.arange(15)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Data Types for ndarrays"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 81,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-01-29T23:14:13.035013Z",
     "start_time": "2019-01-29T23:14:13.006162Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "dtype('int32')"
      ]
     },
     "execution_count": 81,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr1 = np.array([1, 2, 3], dtype=np.float64)\n",
    "arr2 = np.array([1, 2, 3], dtype=np.int32)\n",
    "arr1.dtype\n",
    "arr2.dtype"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 82,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-01-29T23:14:13.083989Z",
     "start_time": "2019-01-29T23:14:13.037578Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "dtype('float64')"
      ]
     },
     "execution_count": 82,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr = np.array([1, 2, 3, 4, 5])\n",
    "arr.dtype\n",
    "float_arr = arr.astype(np.float64)\n",
    "float_arr.dtype"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 83,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-01-29T23:14:13.126346Z",
     "start_time": "2019-01-29T23:14:13.088047Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ 3, -1, -2,  0, 12, 10], dtype=int32)"
      ]
     },
     "execution_count": 83,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr = np.array([3.7, -1.2, -2.6, 0.5, 12.9, 10.1])\n",
    "arr\n",
    "arr.astype(np.int32)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 84,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-01-29T23:14:13.162514Z",
     "start_time": "2019-01-29T23:14:13.130771Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([  1.25,  -9.6 ,  42.  ])"
      ]
     },
     "execution_count": 84,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "numeric_strings = np.array(['1.25', '-9.6', '42'], dtype=np.string_)\n",
    "numeric_strings.astype(float)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 85,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-01-29T23:14:13.192052Z",
     "start_time": "2019-01-29T23:14:13.165405Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ 0.,  1.,  2.,  3.,  4.,  5.,  6.,  7.,  8.,  9.])"
      ]
     },
     "execution_count": 85,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "int_array = np.arange(10)\n",
    "calibers = np.array([.22, .270, .357, .380, .44, .50], dtype=np.float64)\n",
    "int_array.astype(calibers.dtype)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 86,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-01-29T23:14:13.227397Z",
     "start_time": "2019-01-29T23:14:13.194125Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([         0, 1075314688,          0, 1075707904,          0,\n",
       "       1075838976,          0, 1072693248], dtype=uint32)"
      ]
     },
     "execution_count": 86,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "empty_uint32 = np.empty(8, dtype='u4')\n",
    "empty_uint32"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Operations between arrays and scalars"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 87,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-01-29T23:14:13.286476Z",
     "start_time": "2019-01-29T23:14:13.232779Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0.,  0.,  0.],\n",
       "       [ 0.,  0.,  0.]])"
      ]
     },
     "execution_count": 87,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr = np.array([[1., 2., 3.], [4., 5., 6.]])\n",
    "arr\n",
    "arr * arr\n",
    "arr - arr"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 88,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-01-29T23:14:13.327647Z",
     "start_time": "2019-01-29T23:14:13.291406Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 1.    ,  1.4142,  1.7321],\n",
       "       [ 2.    ,  2.2361,  2.4495]])"
      ]
     },
     "execution_count": 88,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "1 / arr\n",
    "arr ** 0.5"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Basic indexing and slicing"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 89,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-01-29T23:14:13.364249Z",
     "start_time": "2019-01-29T23:14:13.331174Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ 0,  1,  2,  3,  4, 12, 12, 12,  8,  9])"
      ]
     },
     "execution_count": 89,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr = np.arange(10)\n",
    "arr\n",
    "arr[5]\n",
    "arr[5:8]\n",
    "arr[5:8] = 12\n",
    "arr"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 90,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-01-29T23:14:13.396617Z",
     "start_time": "2019-01-29T23:14:13.366988Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ 0,  1,  2,  3,  4, 64, 64, 64,  8,  9])"
      ]
     },
     "execution_count": 90,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr_slice = arr[5:8]\n",
    "arr_slice[1] = 12345\n",
    "arr\n",
    "arr_slice[:] = 64\n",
    "arr"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 91,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-01-29T23:14:13.440070Z",
     "start_time": "2019-01-29T23:14:13.399282Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([7, 8, 9])"
      ]
     },
     "execution_count": 91,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr2d = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])\n",
    "arr2d[2]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 92,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-01-29T23:14:13.483992Z",
     "start_time": "2019-01-29T23:14:13.444498Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "3"
      ]
     },
     "execution_count": 92,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr2d[0][2]\n",
    "arr2d[0, 2]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 93,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-01-29T23:14:13.524728Z",
     "start_time": "2019-01-29T23:14:13.487759Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[[ 1,  2,  3],\n",
       "        [ 4,  5,  6]],\n",
       "\n",
       "       [[ 7,  8,  9],\n",
       "        [10, 11, 12]]])"
      ]
     },
     "execution_count": 93,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr3d = np.array([[[1, 2, 3], [4, 5, 6]], [[7, 8, 9], [10, 11, 12]]])\n",
    "arr3d"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 94,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-01-29T23:14:13.566590Z",
     "start_time": "2019-01-29T23:14:13.529049Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[1, 2, 3],\n",
       "       [4, 5, 6]])"
      ]
     },
     "execution_count": 94,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr3d[0]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 95,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-01-29T23:14:13.606574Z",
     "start_time": "2019-01-29T23:14:13.570510Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[[ 1,  2,  3],\n",
       "        [ 4,  5,  6]],\n",
       "\n",
       "       [[ 7,  8,  9],\n",
       "        [10, 11, 12]]])"
      ]
     },
     "execution_count": 95,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "old_values = arr3d[0].copy()\n",
    "arr3d[0] = 42\n",
    "arr3d\n",
    "arr3d[0] = old_values\n",
    "arr3d"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 96,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-01-29T23:14:13.638298Z",
     "start_time": "2019-01-29T23:14:13.609397Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([7, 8, 9])"
      ]
     },
     "execution_count": 96,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr3d[1, 0]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Indexing with slices"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 97,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-01-29T23:14:13.674497Z",
     "start_time": "2019-01-29T23:14:13.641408Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ 1,  2,  3,  4, 64])"
      ]
     },
     "execution_count": 97,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr[1:6]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 98,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-01-29T23:14:13.722641Z",
     "start_time": "2019-01-29T23:14:13.676807Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[1, 2, 3],\n",
       "       [4, 5, 6]])"
      ]
     },
     "execution_count": 98,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr2d\n",
    "arr2d[:2]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 99,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-01-29T23:14:13.763308Z",
     "start_time": "2019-01-29T23:14:13.725503Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[2, 3],\n",
       "       [5, 6]])"
      ]
     },
     "execution_count": 99,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr2d[:2, 1:]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 100,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-01-29T23:14:13.797542Z",
     "start_time": "2019-01-29T23:14:13.768272Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([7])"
      ]
     },
     "execution_count": 100,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr2d[1, :2]\n",
    "arr2d[2, :1]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 101,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-01-29T23:14:13.829403Z",
     "start_time": "2019-01-29T23:14:13.800011Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[1],\n",
       "       [4],\n",
       "       [7]])"
      ]
     },
     "execution_count": 101,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr2d[:, :1]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 102,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-01-29T23:14:13.869857Z",
     "start_time": "2019-01-29T23:14:13.831762Z"
    },
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "arr2d[:2, 1:] = 0"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Boolean indexing"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 103,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-01-29T23:14:13.927286Z",
     "start_time": "2019-01-29T23:14:13.875185Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0.2958, -0.5526,  0.0492,  2.228 ],\n",
       "       [ 0.0616,  0.3488,  0.3072,  1.7355],\n",
       "       [ 0.8838,  0.4705, -0.2036, -0.7349],\n",
       "       [-0.2913, -0.1507, -1.1558,  2.3093],\n",
       "       [-0.9157,  0.5808, -0.3418, -0.2118],\n",
       "       [-0.5258, -0.3511,  0.6861,  0.2156],\n",
       "       [ 0.407 ,  1.6989, -0.7682,  0.7233]])"
      ]
     },
     "execution_count": 103,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "names = np.array(['Bob', 'Joe', 'Will', 'Bob', 'Will', 'Joe', 'Joe'])\n",
    "data = randn(7, 4)\n",
    "names\n",
    "data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 104,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-01-29T23:14:13.962474Z",
     "start_time": "2019-01-29T23:14:13.930532Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ True, False, False,  True, False, False, False], dtype=bool)"
      ]
     },
     "execution_count": 104,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "names == 'Bob'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 105,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-01-29T23:14:13.993105Z",
     "start_time": "2019-01-29T23:14:13.965027Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0.2958, -0.5526,  0.0492,  2.228 ],\n",
       "       [-0.2913, -0.1507, -1.1558,  2.3093]])"
      ]
     },
     "execution_count": 105,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "data[names == 'Bob']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 106,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-01-29T23:14:14.024188Z",
     "start_time": "2019-01-29T23:14:13.995740Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ 2.228 ,  2.3093])"
      ]
     },
     "execution_count": 106,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "data[names == 'Bob', 2:]\n",
    "data[names == 'Bob', 3]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 107,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-01-29T23:14:14.092656Z",
     "start_time": "2019-01-29T23:14:14.026973Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0.0616,  0.3488,  0.3072,  1.7355],\n",
       "       [ 0.8838,  0.4705, -0.2036, -0.7349],\n",
       "       [-0.9157,  0.5808, -0.3418, -0.2118],\n",
       "       [-0.5258, -0.3511,  0.6861,  0.2156],\n",
       "       [ 0.407 ,  1.6989, -0.7682,  0.7233]])"
      ]
     },
     "execution_count": 107,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "names != 'Bob'\n",
    "data[~(names == 'Bob')]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 108,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-01-29T23:14:14.138477Z",
     "start_time": "2019-01-29T23:14:14.096003Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0.2958, -0.5526,  0.0492,  2.228 ],\n",
       "       [ 0.8838,  0.4705, -0.2036, -0.7349],\n",
       "       [-0.2913, -0.1507, -1.1558,  2.3093],\n",
       "       [-0.9157,  0.5808, -0.3418, -0.2118]])"
      ]
     },
     "execution_count": 108,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "mask = (names == 'Bob') | (names == 'Will')\n",
    "mask\n",
    "data[mask]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 109,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-01-29T23:14:14.185709Z",
     "start_time": "2019-01-29T23:14:14.147596Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0.2958,  0.    ,  0.0492,  2.228 ],\n",
       "       [ 0.0616,  0.3488,  0.3072,  1.7355],\n",
       "       [ 0.8838,  0.4705,  0.    ,  0.    ],\n",
       "       [ 0.    ,  0.    ,  0.    ,  2.3093],\n",
       "       [ 0.    ,  0.5808,  0.    ,  0.    ],\n",
       "       [ 0.    ,  0.    ,  0.6861,  0.2156],\n",
       "       [ 0.407 ,  1.6989,  0.    ,  0.7233]])"
      ]
     },
     "execution_count": 109,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "data[data < 0] = 0\n",
    "data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 110,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-01-29T23:14:14.217990Z",
     "start_time": "2019-01-29T23:14:14.188975Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 7.    ,  7.    ,  7.    ,  7.    ],\n",
       "       [ 0.0616,  0.3488,  0.3072,  1.7355],\n",
       "       [ 7.    ,  7.    ,  7.    ,  7.    ],\n",
       "       [ 7.    ,  7.    ,  7.    ,  7.    ],\n",
       "       [ 7.    ,  7.    ,  7.    ,  7.    ],\n",
       "       [ 0.    ,  0.    ,  0.6861,  0.2156],\n",
       "       [ 0.407 ,  1.6989,  0.    ,  0.7233]])"
      ]
     },
     "execution_count": 110,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "data[names != 'Joe'] = 7\n",
    "data"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Fancy indexing"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 111,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-01-29T23:14:14.249242Z",
     "start_time": "2019-01-29T23:14:14.220809Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0.,  0.,  0.,  0.],\n",
       "       [ 1.,  1.,  1.,  1.],\n",
       "       [ 2.,  2.,  2.,  2.],\n",
       "       [ 3.,  3.,  3.,  3.],\n",
       "       [ 4.,  4.,  4.,  4.],\n",
       "       [ 5.,  5.,  5.,  5.],\n",
       "       [ 6.,  6.,  6.,  6.],\n",
       "       [ 7.,  7.,  7.,  7.]])"
      ]
     },
     "execution_count": 111,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr = np.empty((8, 4))\n",
    "for i in range(8):\n",
    "    arr[i] = i\n",
    "arr"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 112,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-01-29T23:14:14.287679Z",
     "start_time": "2019-01-29T23:14:14.252000Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 4.,  4.,  4.,  4.],\n",
       "       [ 3.,  3.,  3.,  3.],\n",
       "       [ 0.,  0.,  0.,  0.],\n",
       "       [ 6.,  6.,  6.,  6.]])"
      ]
     },
     "execution_count": 112,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr[[4, 3, 0, 6]]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 113,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-01-29T23:14:14.331348Z",
     "start_time": "2019-01-29T23:14:14.291190Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 5.,  5.,  5.,  5.],\n",
       "       [ 3.,  3.,  3.,  3.],\n",
       "       [ 1.,  1.,  1.,  1.]])"
      ]
     },
     "execution_count": 113,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr[[-3, -5, -7]]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 114,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-01-29T23:14:14.370629Z",
     "start_time": "2019-01-29T23:14:14.335049Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ 4, 23, 29, 10])"
      ]
     },
     "execution_count": 114,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# more on reshape in Chapter 12\n",
    "arr = np.arange(32).reshape((8, 4))\n",
    "arr\n",
    "arr[[1, 5, 7, 2], [0, 3, 1, 2]]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 115,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-01-29T23:14:14.410769Z",
     "start_time": "2019-01-29T23:14:14.376159Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 4,  7,  5,  6],\n",
       "       [20, 23, 21, 22],\n",
       "       [28, 31, 29, 30],\n",
       "       [ 8, 11,  9, 10]])"
      ]
     },
     "execution_count": 115,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr[[1, 5, 7, 2]][:, [0, 3, 1, 2]]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 116,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-01-29T23:14:14.443015Z",
     "start_time": "2019-01-29T23:14:14.414173Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 4,  7,  5,  6],\n",
       "       [20, 23, 21, 22],\n",
       "       [28, 31, 29, 30],\n",
       "       [ 8, 11,  9, 10]])"
      ]
     },
     "execution_count": 116,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr[np.ix_([1, 5, 7, 2], [0, 3, 1, 2])]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Transposing arrays and swapping axes"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 117,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-01-29T23:14:14.473986Z",
     "start_time": "2019-01-29T23:14:14.445388Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0,  5, 10],\n",
       "       [ 1,  6, 11],\n",
       "       [ 2,  7, 12],\n",
       "       [ 3,  8, 13],\n",
       "       [ 4,  9, 14]])"
      ]
     },
     "execution_count": 117,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr = np.arange(15).reshape((3, 5))\n",
    "arr\n",
    "arr.T"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 118,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-01-29T23:14:14.510071Z",
     "start_time": "2019-01-29T23:14:14.476285Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 4.1301,  2.9255, -1.1329],\n",
       "       [ 2.9255,  5.6135, -2.3854],\n",
       "       [-1.1329, -2.3854,  8.4495]])"
      ]
     },
     "execution_count": 118,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr = np.random.randn(6, 3)\n",
    "np.dot(arr.T, arr)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 119,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-01-29T23:14:14.546882Z",
     "start_time": "2019-01-29T23:14:14.512685Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[[ 0,  1,  2,  3],\n",
       "        [ 8,  9, 10, 11]],\n",
       "\n",
       "       [[ 4,  5,  6,  7],\n",
       "        [12, 13, 14, 15]]])"
      ]
     },
     "execution_count": 119,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr = np.arange(16).reshape((2, 2, 4))\n",
    "arr\n",
    "arr.transpose((1, 0, 2))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 120,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-01-29T23:14:14.595211Z",
     "start_time": "2019-01-29T23:14:14.550384Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[[ 0,  4],\n",
       "        [ 1,  5],\n",
       "        [ 2,  6],\n",
       "        [ 3,  7]],\n",
       "\n",
       "       [[ 8, 12],\n",
       "        [ 9, 13],\n",
       "        [10, 14],\n",
       "        [11, 15]]])"
      ]
     },
     "execution_count": 120,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr\n",
    "arr.swapaxes(1, 2)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Universal Functions: Fast element-wise array functions"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 121,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-01-29T23:14:14.638397Z",
     "start_time": "2019-01-29T23:14:14.600689Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([    1.    ,     2.7183,     7.3891,    20.0855,    54.5982,\n",
       "         148.4132,   403.4288,  1096.6332,  2980.958 ,  8103.0839])"
      ]
     },
     "execution_count": 121,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr = np.arange(10)\n",
    "np.sqrt(arr)\n",
    "np.exp(arr)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 122,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-01-29T23:14:14.676154Z",
     "start_time": "2019-01-29T23:14:14.643697Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ 1.8031,  2.725 , -0.4326, -0.7665,  0.8899, -0.0123,  0.6852,\n",
       "        1.5947])"
      ]
     },
     "execution_count": 122,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x = randn(8)\n",
    "y = randn(8)\n",
    "x\n",
    "y\n",
    "np.maximum(x, y) # element-wise maximum"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 123,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-01-29T23:14:14.715528Z",
     "start_time": "2019-01-29T23:14:14.678366Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(array([-0.7089,  0.1649, -0.0367,  0.1101, -0.9744,  0.5479,  0.5265]),\n",
       " array([-4.,  6., -0.,  0., -5.,  3.,  5.]))"
      ]
     },
     "execution_count": 123,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr = randn(7) * 5\n",
    "np.modf(arr)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Data processing using arrays"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 124,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-01-29T23:14:14.748091Z",
     "start_time": "2019-01-29T23:14:14.718307Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[-5.  , -5.  , -5.  , ..., -5.  , -5.  , -5.  ],\n",
       "       [-4.99, -4.99, -4.99, ..., -4.99, -4.99, -4.99],\n",
       "       [-4.98, -4.98, -4.98, ..., -4.98, -4.98, -4.98],\n",
       "       ..., \n",
       "       [ 4.97,  4.97,  4.97, ...,  4.97,  4.97,  4.97],\n",
       "       [ 4.98,  4.98,  4.98, ...,  4.98,  4.98,  4.98],\n",
       "       [ 4.99,  4.99,  4.99, ...,  4.99,  4.99,  4.99]])"
      ]
     },
     "execution_count": 124,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "points = np.arange(-5, 5, 0.01) # 1000 equally spaced points\n",
    "xs, ys = np.meshgrid(points, points)\n",
    "ys"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 125,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-01-29T23:14:14.780105Z",
     "start_time": "2019-01-29T23:14:14.750749Z"
    },
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "from matplotlib.pyplot import imshow, title"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 126,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-01-29T23:14:15.327794Z",
     "start_time": "2019-01-29T23:14:14.783341Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.text.Text at 0x12303d450>"
      ]
     },
     "execution_count": 126,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x11fddfa50>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import matplotlib.pyplot as plt\n",
    "z = np.sqrt(xs ** 2 + ys ** 2)\n",
    "z\n",
    "plt.imshow(z, cmap=plt.cm.gray); plt.colorbar()\n",
    "plt.title(\"Image plot of $\\sqrt{x^2 + y^2}$ for a grid of values\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 127,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-01-29T23:14:15.366573Z",
     "start_time": "2019-01-29T23:14:15.331375Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.figure.Figure at 0x11fddfa10>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.draw()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Expressing conditional logic as array operations"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 128,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-01-29T23:14:15.393984Z",
     "start_time": "2019-01-29T23:14:15.369329Z"
    },
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "xarr = np.array([1.1, 1.2, 1.3, 1.4, 1.5])\n",
    "yarr = np.array([2.1, 2.2, 2.3, 2.4, 2.5])\n",
    "cond = np.array([True, False, True, True, False])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 129,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-01-29T23:14:15.431515Z",
     "start_time": "2019-01-29T23:14:15.396446Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[1.1000000000000001, 2.2000000000000002, 1.3, 1.3999999999999999, 2.5]"
      ]
     },
     "execution_count": 129,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "result = [(x if c else y)\n",
    "          for x, y, c in zip(xarr, yarr, cond)]\n",
    "result"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 130,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-01-29T23:14:15.467809Z",
     "start_time": "2019-01-29T23:14:15.434753Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ 1.1,  2.2,  1.3,  1.4,  2.5])"
      ]
     },
     "execution_count": 130,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "result = np.where(cond, xarr, yarr)\n",
    "result"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 131,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-01-29T23:14:15.503116Z",
     "start_time": "2019-01-29T23:14:15.470466Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 2.    ,  2.    , -0.0846, -0.4543],\n",
       "       [-1.3269, -0.309 ,  2.    , -0.2065],\n",
       "       [ 2.    ,  2.    ,  2.    ,  2.    ],\n",
       "       [-1.2337,  2.    ,  2.    , -0.32  ]])"
      ]
     },
     "execution_count": 131,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr = randn(4, 4)\n",
    "arr\n",
    "np.where(arr > 0, 2, -2)\n",
    "np.where(arr > 0, 2, arr) # set only positive values to 2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 132,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-01-29T23:14:15.538066Z",
     "start_time": "2019-01-29T23:14:15.505443Z"
    },
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# Not to be executed\n",
    "cond1 = np.array([True, False, True, True, False])\n",
    "cond2 = np.array([False, True, False, True, False])\n",
    "result = []\n",
    "for i in range(cond1.shape[0]):\n",
    "    if cond1[i] and cond2[i]:\n",
    "        result.append(0)\n",
    "    elif cond1[i]:\n",
    "        result.append(1)\n",
    "    elif cond2[i]:\n",
    "        result.append(2)\n",
    "    else:\n",
    "        result.append(3)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 133,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-01-29T23:14:15.573493Z",
     "start_time": "2019-01-29T23:14:15.540940Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([1, 2, 1, 0, 3])"
      ]
     },
     "execution_count": 133,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Not to be executed\n",
    "\n",
    "np.where(cond1 & cond2, 0,\n",
    "         np.where(cond1, 1,\n",
    "                  np.where(cond2, 2, 3)))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 134,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-01-29T23:14:15.619442Z",
     "start_time": "2019-01-29T23:14:15.576836Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([1, 2, 1, 0, 3])"
      ]
     },
     "execution_count": 134,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Not to be executed\n",
    "\n",
    "result = 1 * (cond1 & ~cond2) + 2 * (cond2 & ~cond1) + 3 * ~(cond1 | cond2)\n",
    "result"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Mathematical and statistical methods"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 135,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-01-29T23:14:15.658398Z",
     "start_time": "2019-01-29T23:14:15.624480Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "-5.0056687710830712"
      ]
     },
     "execution_count": 135,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr = np.random.randn(5, 4) # normally-distributed data\n",
    "arr.mean()\n",
    "np.mean(arr)\n",
    "arr.sum()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 136,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-01-29T23:14:15.690220Z",
     "start_time": "2019-01-29T23:14:15.662063Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([-3.0668, -3.0318, -2.5332,  3.6261])"
      ]
     },
     "execution_count": 136,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr.mean(axis=1)\n",
    "arr.sum(0)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 137,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-01-29T23:14:15.734165Z",
     "start_time": "2019-01-29T23:14:15.692620Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[  0,   0,   0],\n",
       "       [  3,  12,  60],\n",
       "       [  6,  42, 336]])"
      ]
     },
     "execution_count": 137,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr = np.array([[0, 1, 2], [3, 4, 5], [6, 7, 8]])\n",
    "arr.cumsum(0)\n",
    "arr.cumprod(1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Methods for boolean arrays"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 138,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-01-29T23:14:15.770981Z",
     "start_time": "2019-01-29T23:14:15.737101Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "48"
      ]
     },
     "execution_count": 138,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr = randn(100)\n",
    "(arr > 0).sum() # Number of positive values"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 139,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-01-29T23:14:15.801693Z",
     "start_time": "2019-01-29T23:14:15.773849Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "False"
      ]
     },
     "execution_count": 139,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "bools = np.array([False, False, True, False])\n",
    "bools.any()\n",
    "bools.all()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Sorting"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 140,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-01-29T23:14:15.836008Z",
     "start_time": "2019-01-29T23:14:15.804332Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([-0.8406, -0.2484,  0.3052,  0.7042,  1.0974,  1.2984,  1.4877,\n",
       "        1.8935])"
      ]
     },
     "execution_count": 140,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr = randn(8)\n",
    "arr\n",
    "arr.sort()\n",
    "arr"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 141,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-01-29T23:14:15.877213Z",
     "start_time": "2019-01-29T23:14:15.838771Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0.0869,  0.9291,  1.2279],\n",
       "       [-0.7784, -0.4596, -0.0664],\n",
       "       [-0.7964, -0.435 ,  0.4928],\n",
       "       [-0.8799, -0.0144,  0.6569],\n",
       "       [-0.8518,  0.3075,  1.8998]])"
      ]
     },
     "execution_count": 141,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr = randn(5, 3)\n",
    "arr\n",
    "arr.sort(1)\n",
    "arr"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 142,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-01-29T23:14:15.911936Z",
     "start_time": "2019-01-29T23:14:15.880175Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "-1.6270693069665767"
      ]
     },
     "execution_count": 142,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "large_arr = randn(1000)\n",
    "large_arr.sort()\n",
    "large_arr[int(0.05 * len(large_arr))] # 5% quantile"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Unique and other set logic"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 143,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-01-29T23:14:15.945838Z",
     "start_time": "2019-01-29T23:14:15.914902Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([1, 2, 3, 4])"
      ]
     },
     "execution_count": 143,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "names = np.array(['Bob', 'Joe', 'Will', 'Bob', 'Will', 'Joe', 'Joe'])\n",
    "np.unique(names)\n",
    "ints = np.array([3, 3, 3, 2, 2, 1, 1, 4, 4])\n",
    "np.unique(ints)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 144,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-01-29T23:14:15.974814Z",
     "start_time": "2019-01-29T23:14:15.948159Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['Bob', 'Joe', 'Will']"
      ]
     },
     "execution_count": 144,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "sorted(set(names))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 145,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-01-29T23:14:16.003517Z",
     "start_time": "2019-01-29T23:14:15.977137Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ True, False, False,  True,  True, False,  True], dtype=bool)"
      ]
     },
     "execution_count": 145,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "values = np.array([6, 0, 0, 3, 2, 5, 6])\n",
    "np.in1d(values, [2, 3, 6])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## File input and output with arrays"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Storing arrays on disk in binary format"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 146,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-01-29T23:14:16.038518Z",
     "start_time": "2019-01-29T23:14:16.005952Z"
    },
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "arr = np.arange(10)\n",
    "np.save('some_array', arr)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 147,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-01-29T23:14:16.089897Z",
     "start_time": "2019-01-29T23:14:16.042243Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])"
      ]
     },
     "execution_count": 147,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.load('some_array.npy')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 148,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-01-29T23:14:16.127552Z",
     "start_time": "2019-01-29T23:14:16.092779Z"
    },
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "np.savez('array_archive.npz', a=arr, b=arr)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 149,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-01-29T23:14:16.168260Z",
     "start_time": "2019-01-29T23:14:16.130086Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])"
      ]
     },
     "execution_count": 149,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arch = np.load('array_archive.npz')\n",
    "arch['b']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 150,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-01-29T23:14:16.463760Z",
     "start_time": "2019-01-29T23:14:16.172047Z"
    },
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "!rm some_array.npy\n",
    "!rm array_archive.npz"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Saving and loading text files"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 154,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-01-30T00:59:41.408289Z",
     "start_time": "2019-01-30T00:59:41.252026Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1,2,3\r\n",
      "4,5,6\r\n",
      "7,8,9\r\n"
     ]
    }
   ],
   "source": [
    "!cat array_ext.txt"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 155,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-01-30T00:59:58.889942Z",
     "start_time": "2019-01-30T00:59:58.851874Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 1.,  2.,  3.],\n",
       "       [ 4.,  5.,  6.],\n",
       "       [ 7.,  8.,  9.]])"
      ]
     },
     "execution_count": 155,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr = np.loadtxt('array_ext.txt', delimiter=',')\n",
    "arr"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Linear algebra"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 157,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-01-30T01:03:13.537327Z",
     "start_time": "2019-01-30T01:03:13.464001Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[  28.,   64.],\n",
       "       [  67.,  181.]])"
      ]
     },
     "execution_count": 157,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x = np.array([[1., 2., 3.], [4., 5., 6.]])\n",
    "y = np.array([[6., 23.], [-1, 7], [8, 9]])\n",
    "x\n",
    "y\n",
    "x.dot(y)  # equivalently np.dot(x, y)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 160,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-01-30T01:03:29.986371Z",
     "start_time": "2019-01-30T01:03:29.953338Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([  6.,  15.])"
      ]
     },
     "execution_count": 160,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.dot(x, np.ones(3))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 164,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-01-30T14:24:54.580870Z",
     "start_time": "2019-01-30T14:24:54.528497Z"
    },
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "np.random.seed(12345)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 163,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-01-30T01:05:01.676751Z",
     "start_time": "2019-01-30T01:05:01.625689Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ -6.9271,   7.389 ,   6.1227,  -7.1163,  -4.9215],\n",
       "       [  0.    ,  -3.9735,  -0.8671,   2.9747,  -5.7402],\n",
       "       [  0.    ,   0.    , -10.2681,   1.8909,   1.6079],\n",
       "       [  0.    ,   0.    ,   0.    ,  -1.2996,   3.3577],\n",
       "       [  0.    ,   0.    ,   0.    ,   0.    ,   0.5571]])"
      ]
     },
     "execution_count": 163,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from numpy.linalg import inv, qr\n",
    "X = randn(5, 5)\n",
    "mat = X.T.dot(X)\n",
    "inv(mat)\n",
    "mat.dot(inv(mat))\n",
    "q, r = qr(mat)\n",
    "r"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Random number generation"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-01-29T23:14:16.717148Z",
     "start_time": "2019-01-29T23:14:10.622Z"
    },
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "samples = np.random.normal(size=(4, 4))\n",
    "samples"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-01-29T23:14:16.719408Z",
     "start_time": "2019-01-29T23:14:10.625Z"
    },
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "from random import normalvariate\n",
    "N = 1000000\n",
    "%timeit samples = [normalvariate(0, 1) for _ in xrange(N)]\n",
    "%timeit np.random.normal(size=N)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Example: Random Walks"
   ]
  },
  {
   "cell_type": "raw",
   "metadata": {},
   "source": [
    "import random\n",
    "position = 0\n",
    "walk = [position]\n",
    "steps = 1000\n",
    "for i in xrange(steps):\n",
    "    step = 1 if random.randint(0, 1) else -1\n",
    "    position += step\n",
    "    walk.append(position)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 165,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-01-30T15:02:59.096651Z",
     "start_time": "2019-01-30T15:02:59.039746Z"
    },
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "np.random.seed(12345)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 166,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-01-30T15:03:43.002112Z",
     "start_time": "2019-01-30T15:03:42.967303Z"
    },
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "nsteps = 1000\n",
    "draws = np.random.randint(0, 2, size=nsteps)\n",
    "steps = np.where(draws > 0, 1, -1)\n",
    "walk = steps.cumsum()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 167,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-01-30T15:03:44.152414Z",
     "start_time": "2019-01-30T15:03:44.118232Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "31"
      ]
     },
     "execution_count": 167,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "walk.min()\n",
    "walk.max()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-01-29T23:14:16.726384Z",
     "start_time": "2019-01-29T23:14:10.707Z"
    },
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "(np.abs(walk) >= 10).argmax()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Simulating many random walks at once"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-01-29T23:14:16.728023Z",
     "start_time": "2019-01-29T23:14:10.711Z"
    },
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "nwalks = 5000\n",
    "nsteps = 1000\n",
    "draws = np.random.randint(0, 2, size=(nwalks, nsteps)) # 0 or 1\n",
    "steps = np.where(draws > 0, 1, -1)\n",
    "walks = steps.cumsum(1)\n",
    "walks"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-01-29T23:14:16.729938Z",
     "start_time": "2019-01-29T23:14:10.714Z"
    },
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "walks.max()\n",
    "walks.min()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-01-29T23:14:16.731597Z",
     "start_time": "2019-01-29T23:14:10.717Z"
    },
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "hits30 = (np.abs(walks) >= 30).any(1)\n",
    "hits30\n",
    "hits30.sum() # Number that hit 30 or -30"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-01-29T23:14:16.733399Z",
     "start_time": "2019-01-29T23:14:10.721Z"
    },
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "crossing_times = (np.abs(walks[hits30]) >= 30).argmax(1)\n",
    "crossing_times.mean()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-01-29T23:14:16.735504Z",
     "start_time": "2019-01-29T23:14:10.726Z"
    },
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "steps = np.random.normal(loc=0, scale=0.25,\n",
    "                         size=(nwalks, nsteps))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "\n"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 2",
   "language": "python",
   "name": "python2"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.13"
  },
  "toc": {
   "nav_menu": {},
   "number_sections": true,
   "sideBar": true,
   "skip_h1_title": false,
   "toc_cell": false,
   "toc_position": {
    "height": "660px",
    "left": "0px",
    "right": "1099px",
    "top": "106px",
    "width": "341px"
   },
   "toc_section_display": "block",
   "toc_window_display": true
  },
  "varInspector": {
   "cols": {
    "lenName": 16,
    "lenType": 16,
    "lenVar": 40
   },
   "kernels_config": {
    "python": {
     "delete_cmd_postfix": "",
     "delete_cmd_prefix": "del ",
     "library": "var_list.py",
     "varRefreshCmd": "print(var_dic_list())"
    },
    "r": {
     "delete_cmd_postfix": ") ",
     "delete_cmd_prefix": "rm(",
     "library": "var_list.r",
     "varRefreshCmd": "cat(var_dic_list()) "
    }
   },
   "types_to_exclude": [
    "module",
    "function",
    "builtin_function_or_method",
    "instance",
    "_Feature"
   ],
   "window_display": false
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
